package com.yuanrui.subject.domain.service.impl;

import com.alibaba.fastjson.JSON;
import com.yuanrui.subject.common.entity.PageResult;
import com.yuanrui.subject.common.enums.IsDeletedFlagEnum;
import com.yuanrui.subject.common.enums.SubjectLikedStatusEnum;
import com.yuanrui.subject.common.redis.RedisUtil;
import com.yuanrui.subject.common.util.LoginUtil;
import com.yuanrui.subject.domain.convert.SubjectLikedBOConverter;
import com.yuanrui.subject.domain.entity.SubjectLikedBO;
import com.yuanrui.subject.domain.entity.SubjectLikedMessage;
import com.yuanrui.subject.domain.service.SubjectLikedDomainService;
import com.yuanrui.subject.infra.basic.entity.SubjectInfo;
import com.yuanrui.subject.infra.basic.entity.SubjectLiked;
import com.yuanrui.subject.infra.basic.service.SubjectLikedService;
import com.yuanrui.subject.infra.basic.service.impl.SubjectInfoServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * 题目点赞表 领域service实现了
 *
 * @author yuanrui
 * @since 2024-07-21 17:27:42
 */
@Service
@Slf4j
public class SubjectLikedDomainServiceImpl implements SubjectLikedDomainService {

    @Resource
    private SubjectLikedService subjectLikedService;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private RocketMQTemplate rocketMQTemplate;

    private static final String SUBJECT_LIKED_KEY = "subject:liked";

    private static final String SUBJECT_LIKED_COUNT_KEY = "subject:liked:count";

    private static final String SUBJECT_LIKED_DETAIL_KEY = "subject:liked:detail";
    @Resource
    private SubjectInfoServiceImpl subjectInfoService;

    @Override
    public void add(SubjectLikedBO subjectLikedBO) {
        Long subjectId = subjectLikedBO.getSubjectId();
        String userId = subjectLikedBO.getLikeUserId();
        Integer status = subjectLikedBO.getStatus();
//        String hashKey = buildSubjectLikedKey(subjectId, userId);
//        redisUtil.putHash(SUBJECT_LIKED_KEY, hashKey, status);
        SubjectLikedMessage subjectLikedMessage = new SubjectLikedMessage();
        subjectLikedMessage.setSubjectId(subjectId);
        subjectLikedMessage.setLikeUserId(userId);
        subjectLikedMessage.setStatus(status);
        //发送消息
        rocketMQTemplate.convertAndSend("subject-liked", JSON.toJSONString(subjectLikedMessage));
        //记录题目被谁点赞
        String detailKey = SUBJECT_LIKED_DETAIL_KEY + ":" + subjectId + ":" + userId;
        //记录题目点赞数
        String countKey = SUBJECT_LIKED_COUNT_KEY + ":" + subjectId;
        if (SubjectLikedStatusEnum.LIKED.getCode().equals(status)) {
            redisUtil.increment(countKey, 1);
            redisUtil.set(detailKey, "1");
        } else {
            Integer anInt = redisUtil.getInt(countKey);
            if (Objects.isNull(anInt) || anInt <= 0) {
                return;
            }
            redisUtil.increment(countKey, -1);
            redisUtil.del(detailKey);
        }
    }

    private String buildSubjectLikedKey(Long subjectId, String userId) {
        return redisUtil.buildKey(subjectId.toString(), userId);
    }

    @Override
    public Boolean update(SubjectLikedBO subjectLikedBO) {
        SubjectLiked subjectLiked = SubjectLikedBOConverter.INSTANCE.convertBOToEntity(subjectLikedBO);
        return subjectLikedService.update(subjectLiked) > 0;
    }

    @Override
    public Boolean delete(SubjectLikedBO subjectLikedBO) {
        SubjectLiked subjectLiked = new SubjectLiked();
        subjectLiked.setId(subjectLikedBO.getId());
        subjectLiked.setIsDeleted(IsDeletedFlagEnum.DELETED.getCode());
        return subjectLikedService.update(subjectLiked) > 0;
    }

    /**
     * 获取当前是否被点赞过
     */
    @Override
    public boolean getLikedStatus(Long subjectId, String userId) {
        String hashKey = SUBJECT_LIKED_DETAIL_KEY + ":" + buildSubjectLikedKey(subjectId, userId);
        return redisUtil.exist(hashKey);
    }

    @Override
    public Integer getLikedCount(Long subjectId) {
        String countKey = SUBJECT_LIKED_COUNT_KEY + ":" + subjectId;
        Integer count = redisUtil.getInt(countKey);
        if (Objects.isNull(count) || count <= 0) {
            return 0;
        }
        return count;
    }

    /**
     * 定时同步数据到数据库
     */
    @Override
    public void syncLiked() {
        Map<Object, Object> subjectLikedMap = redisUtil.getHashAndDelete(SUBJECT_LIKED_KEY);
        if (log.isDebugEnabled()) {
            log.debug("syncLiked:{}", subjectLikedMap);
        }
        if (Objects.isNull(subjectLikedMap) || subjectLikedMap.isEmpty()) {
            return;
        }
        //批量同步到数据库
        List<SubjectLiked> subjectLikedList = new LinkedList<>();
        subjectLikedMap.forEach((key, value) -> {
            SubjectLiked subjectLiked = new SubjectLiked();
            //得到题目id和用户id的数组
            String[] likedKey = key.toString().split(":");
            if (likedKey.length != 2) {
                return;
            }
            subjectLiked.setSubjectId(Long.parseLong(likedKey[0]));
            subjectLiked.setLikeUserId(likedKey[1]);
            subjectLiked.setStatus(Integer.parseInt(value.toString()));
            subjectLiked.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
            subjectLikedList.add(subjectLiked);
        });
        //如果数据库中已经存在，就更新点赞状态，否则插入
        subjectLikedList.forEach(subjectLiked -> {
            SubjectLiked query = subjectLikedService.queryBySubjectId(subjectLiked);
            if (Objects.isNull(query)) {
                subjectLikedService.insert(subjectLiked);
            } else {
                subjectLiked.setId(query.getId());
                Integer status = query.getStatus() == 1 ? 0 : 1;
                subjectLiked.setStatus(status);
                subjectLikedService.update(subjectLiked);
            }
        });
    }

    @Override
    public PageResult<SubjectLikedBO> getSubjectLikedPage(SubjectLikedBO subjectLikedBO) {
        PageResult<SubjectLikedBO> pageResult = new PageResult<>();
        pageResult.setPageNo(subjectLikedBO.getPageNo());
        pageResult.setPageSize(subjectLikedBO.getPageSize());
        int start = (subjectLikedBO.getPageNo() - 1) * subjectLikedBO.getPageSize();
        SubjectLiked subjectLiked = SubjectLikedBOConverter.INSTANCE.convertBOToEntity(subjectLikedBO);
        subjectLiked.setLikeUserId(LoginUtil.getLoginId());
        int count = subjectLikedService.countByCondition(subjectLiked);
        if (count == 0) {
            return pageResult;
        }
        List<SubjectLiked> subjectLikedList = subjectLikedService.queryPage(subjectLiked, start, subjectLikedBO.getPageSize());
        List<SubjectLikedBO> subjectLikedBOS = SubjectLikedBOConverter.INSTANCE.convertEntityListToBOList(subjectLikedList);
        subjectLikedBOS.forEach(bo -> {
            SubjectInfo subjectInfo = subjectInfoService.queryById(bo.getSubjectId());
            bo.setSubjectName(subjectInfo.getSubjectName());
        });
        pageResult.setResult(subjectLikedBOS);
        pageResult.setRecords(count);
        return pageResult;
    }

    @Override
    public void syncLikedByMessage(SubjectLikedBO subjectLikedBO) {
        //使用消息队列同步点赞数
        List<SubjectLiked> subjectLikedList = new LinkedList<>();
        SubjectLiked subjectLiked = new SubjectLiked();
        subjectLiked.setSubjectId(subjectLikedBO.getSubjectId());
        subjectLiked.setLikeUserId(subjectLikedBO.getLikeUserId());
        subjectLiked.setStatus(subjectLikedBO.getStatus());
        subjectLikedList.add(subjectLiked);
        //如果数据库中已经存在，就更新点赞状态，否则插入
        subjectLikedList.forEach(subjectLike -> {
            SubjectLiked query = subjectLikedService.queryBySubjectId(subjectLike);
            if (Objects.isNull(query)) {
                subjectLikedService.insert(subjectLike);
            } else {
                subjectLike.setId(query.getId());
                Integer status = query.getStatus() == 1 ? 0 : 1;
                subjectLike.setStatus(status);
                subjectLikedService.update(subjectLike);
            }
        });
    }

}
